Genero FGL為一個出自於資料庫的語言,但怎麼和資料庫搭上邊的,我們還是需要來做一下理解。
原始從 i4GL開始,既然是資料庫的附屬查詢工具,那應該沒話說:從開始執行就應該是搭著資料庫一起走,直到結束時才中斷與資料庫的連線。但Genero已經不走這一套。
在前面的章節中,我們談論 FGLPROFILE 時有提到,FGLPROFILE可以設定資料庫的連線字串,設定後就可使用 DATABASE 這個指令與資料庫連線。
DATABASE ds #FGLPROFILE中設定數據庫代碼為ds
MAIN
DEFINE i INT
SELECT COUNT(*) INTO i FROM table_A
END MAIN
這種寫法表示在程式一開始執行就可以連上資料庫
MAIN
DEFINE i INT
WHENEVER ERROR CONTINUE
SELECT COUNT(*) INTO i FROM table_A
DISPLAY 'NO CONNECT:',i,' STATUS:',SQLCA.SQLCODE,":",SQLERRMESSAGE
DATABASE ds
SELECT COUNT(*) INTO i FROM table_A
DISPLAY 'NO CONNECT:',i,' STATUS:',SQLCA.SQLCODE,":",SQLERRMESSAGE
這樣的寫法就表示說,程式一開始是沒有連結到資料庫的,以致於執行上出錯了。後來透過DATABASE才連上資料庫,取出正確的筆數
額外說明:
資料庫的欄位型態是可以異動 (alter)的。
當資料庫型態異動的時候,意味著程式可能需要跟著改。這太麻煩,因此FGL可使用 DEFINE...LIKE 的做法,讓變數去參考資料庫欄位的資料型態(datatype)與長度(length)。此處參考資料庫格式,並不是每次要編譯的時後才去資料庫抓取或理解,而是要事先準備好的,檔案格式為『.sch』
透過上圖,大概可以理解 .sch 是由 fgldbsch 這個工具連到資料庫,讀取系統表格分析後產出的紀錄檔 (如 ds 資料庫,經過 fgldbsch 之後就會產出 ds.sch 的結構檔,提供使用。
標題這樣下的時候,應該就可以聯想到,當 DATABASE 出現在程式 (MAIN) 與GLOBAL設定的前端時,除了啟動資料庫連線外,還有『在編譯時要求讀取 sch 檔』的功能
當程式中不想開起就連上db,而將 DATABASE 移位到程式中間,甚至是使用 CONNECT TO指令進行連線,此時就需要在程式的最上方宣告處,改用 SCHEMA ds 來讓 fglcomp (編譯器) 理解到稍後是需要用 ds.sch 來替換 LIKE 後面的格式
通常的定義是 DEFINE i INT,而若參照的語法,則可以寫成 DEFINE i LIKE table_id.column_id
這樣的寫法可以讓該變數(i)在編譯時,使用column_id 的型態與長度進行編譯。若有更改,怎辦?重新編譯一次呀。這樣的好處在:若有alter時則重編譯就可以執行。
怎麼用說完了,接下來看一下 ds.sch 怎麼生出來的 (ds.4db是衍生品,語法替換出來的產物,故研究 .sch即可)
我個人認為這是一個非常神奇的工具,它可以協助我們將 db的表格欄位型態倒出來,讓我們編譯程式的時候減少去背誦記憶到底要用哪些型態。甚至透過 sch 的預載,可以很便利的協助我們在 studio 中拉出DML(資料關聯圖)
customer^customer_num^258^4^1^
customer^customer_name^256^50^2^
customer^customer_address^0^100^3^
order^order_num^258^4^1^
order^order_custnum^258^4^2^
order^order_date^263^4^3^
order^order_total^261^1538^4^
上面是 FGL線上文件中列出的範例,使用 ^(hat) 進行分隔,欄位分別是 table id / Column id/ 欄位型態/ 欄位長度 / 順序 等。
欄位型態並不是『真正在資料庫中的資料型態』。WHAT? 每種資料庫都有不同形態,大家各玩各的未來還有甚麼整合的希望,所以這邊的資料型態紀錄的是『參考INFORMIX轉換過的資料型態』。
長度則是經過轉換換算的。例如 INT/SMALLINT/CHAR/VARCHAR 這些都有固定的長度,但若 DECIMAL(ORACLE則是NUMBER)就會經過轉換轉為單一數字。另外,若這個欄位具有 KEY (PK)身分的話,會再加上一個數值。詳細轉換公式可以參考: https://4js.com/online_documentation/fjs-fgl-manual-html/index.html#fgl-topics/c_fgl_DatabaseSchema_018.html
上方提到:這是一種參考 INFORMIX 而來的轉換型態,可是不可能兩種不同廠牌的資料庫具有同樣多的資料型態。此時就需要用到 fgldbsch 的密技:對應表
fgldbsch常用指令 (不常用的先濾除)
<topprd:/u1/topprd> fgldbsch -h
Usage: fgldbsch [options]
-ct : Show data type conversion tables. 顯示轉換表
-cx dbtype : Show data type converstion table for a given db type. 使用轉換表
-db name : Database name. 資料庫名
-dv name : Database driver. 資料庫驅動
-un user : Database User name. 資料庫用戶
-up password : Database User password. 密碼
-ow name : Database schema/tables owner. 資料庫/表擁有者
-of name : Output filename prefix. Default is database name. 產出檔名
<topprd:/u1/topprd>
其中最需要注意的是 fgldbsch -ct 這個指令
這個指令列出了ORACLE一些與 INFORMIX有差異的資料型態,然後分選項A/ 選項B,就是想問你會怎麼要fgldbsch調整?相當於可以讓 fgldbsch 來做選擇規則。
例如:ORACLE的 DATE是可以存時分秒的,INFORMIX的DATE不行,必須要到 DATETIME YEAR TO SECOND才可以存時分秒。所以,fgldbsch可以讓你決定,要轉換為 DATE或是DATETIME YEAR TO SECOND
這張表需要在開工前仔細確認好原則,所以在開始撰寫連線新的 DB 廠牌時,最重要的就是把型態給決定下來。
這張表格中的序列,從常用的到不常用的依序排列。意思是,如果我要改的是第五項,則我要宣告 1-5 項。(1-4沒要改,那也要宣告!!)
所以宣告時 fgldbsch 指令如下
fgldbsch -db ds -ow ds -ie -cv AAAAB
那?我第 7,9 項想改為 B 其他保持預設值 A 豈不是 -cv AAAAAABAB ?是的,這就是正確答案。
透過仔細地閱讀新 db 的差異,確認需要使用的資料表對應方式,這是撰寫前的起手式。能掌握好這段的配置,在後續的開發可以避免掉許多資料型態不合的錯誤。
其實這個段落章節,應該是由部門的輝哥來撰寫,更為精彩。在此感謝為 Genero開疆闢土的大佬們。